#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
@Project ：tools
@File    ：tkinter应用模板
@IDE     ：PyCharm
@Author  ：Kongbai
@Date    ：2021/9/27 14:17
'''
import json
import threading
import time
import tkinter as tk
import webbrowser
import qrcode
import requests
from PIL import ImageTk, Image
import util
from config import Config,declaration
from queue import Queue, Empty
from tkinter import ttk, messagebox
from tkhtmlview import HTMLScrolledText


class ApplicationUI(tk.Frame):
    def __init__(self, configer):
        super().__init__(configer.window)
        self.window_title=configer.title
        self.master = configer.window  # 父窗口
        self.pack()
        self.create_widgets()  # 注册组件
        self.style_widgets()  # 加载公共组件的样式

    def create_widgets(self):
        """
        创建组件
        :return:
        """
        # 注册左侧主窗体frame
        self.left_frame = tk.Frame(master=self)
        self.left_frame.grid(row=0, column=0, ipadx=40, sticky=tk.NS)
        self.left_frame.grid_propagate(0)

        # 注册左侧按钮
        self.button_list = [0 for _ in range(6)]
        self.button_value = ['搜索视频', '用户中心', '搜寻结果', '下载队列', '已完成', '关于']
        for j in range(6):
            self.button_list[j] = tk.Button(self.left_frame, text=self.button_value[j], height=1)
            self.button_list[j].bind("<Button-1>", self.show_frame)
            self.button_list[j].bind("<Enter>", self.on_enter)
            self.button_list[j].bind("<Leave>", self.on_leave)
            self.button_list[j].pack(fill=tk.BOTH, expand=1)  # 四边都撑满父窗口

        # 创建右侧主窗体frame
        self.right_frame = tk.Frame(master=self)
        self.right_frame.grid(row=0, column=1)
        self.right_frame.grid_propagate(0)  # 主要用于撑满右侧空间
        # 加载背景图片
        self.bg_img = tk.Label(self.right_frame, image=self.bg_photo[1], compound=tk.CENTER)  # 背景
        self.bg_img.pack()
        # 标注每个frame的显示的位置
        self.frame_list_xy = [(250, 250), (850, 150), (500, 50), (500, 50), (500, 50), (300, 200)]
        self.right_frame_list = [0 for _ in range(6)]
        for i in range(6):  # 循环注册各个frame
            self.right_frame_list[i] = tk.Frame(master=self.right_frame)
            if i == self.now_show_frame_index:
                self.right_frame_list[i].grid(row=0, column=1, padx=self.frame_list_xy[i][0],
                                              pady=self.frame_list_xy[i][1])
        # 循环注册右侧主窗体下的各个frame中的控件
        for i in range(6):
            eval(f"self.create_frame{i}()")

    def style_widgets(self):
        """
        设置公共组件的样式
        :return:
        """
        left_width = 100
        right_width = self.configer.win_width - left_width
        common_height = self.configer.win_height
        self.left_frame.config(width=left_width, height=common_height, bg="#4f8bf5")
        self.right_frame.config(width=right_width, height=common_height, bg="#9bb6d2")

        # 设置每个frame的背景色
        for i in self.right_frame_list:
            i.config(bg="#aeddfb")

        # 设置每个左侧按钮的样式
        for k, i in enumerate(self.button_list):
            if k == self.now_show_frame_index:
                i.config(bg="white", font=('微软雅黑', 15), relief=tk.GROOVE)
            else:
                i.config(bg="#9bb6d2", font=('微软雅黑', 15), relief=tk.GROOVE)

        # 表格样式
        style_table = ttk.Style()
        style_table.configure("Treeview.Heading", font=("微软雅黑", 13))
        style_table.configure("Treeview", font=("微软雅黑", 12),
                              background="#d9edf7",
                              foreground="black",
                              )

    def create_frame0(self):
        self.go_B_index_button = tk.Button(self.right_frame_list[0], text="去B站首页", font=('微软雅黑', 13), bg='#aeddfb',
                                           relief=tk.GROOVE, command=self.browser_go_b_index)
        self.go_B_index_button.grid(row=0, column=0)
        self.search_input = tk.Entry(self.right_frame_list[0], bg='#fcfdff', font=('微软雅黑', 15), relief=tk.GROOVE)
        self.search_input.grid(row=0, column=1, ipadx=180, ipady=5)
        self.search_btn = tk.Button(self.right_frame_list[0], text="搜索视频", bg='#169fe6', font=('微软雅黑', 13), fg="white",
                                    relief=tk.GROOVE, command=self.event_search_movie)
        self.search_btn.grid(row=0, column=2)

    def create_frame1(self):
        self.fav_list = dict()
        self.fav_movie_list = dict()

        self.select_fav = tk.StringVar()
        self.select_fav.set('选择我的收藏夹')

        self.fav_combobox = ttk.Combobox(self.right_frame_list[1], height=15, width=30, state='readonly',
                                         cursor='arrow', font=('微软雅黑', 15),
                                         textvariable=self.select_fav, values=self.fav_list)
        self.fav_combobox.pack()
        self.fav_combobox.bind('<<ComboboxSelected>>', self.even_selected_dir)

        self.select_fav_movie = tk.StringVar()
        self.select_fav_movie.set('选择收藏夹视频')
        self.fav_movie_combobox = ttk.Combobox(self.right_frame_list[1], height=15, width=30, state='readonly',
                                               cursor='arrow',
                                               font=('微软雅黑', 15), textvariable=self.select_fav_movie,
                                               values=list(self.fav_movie_list.keys()), )
        self.fav_movie_combobox.pack()
        self.fav_movie_combobox.bind('<<ComboboxSelected>>', self.even_selected_movie)

        self.go_fav_index_button = tk.Button(self.right_frame_list[1], text="去我的网站收藏页", font=('微软雅黑', 15), bg='#aeddfb',
                                             relief=tk.GROOVE, command=self.browser_go_fav_index)
        self.go_fav_index_button.pack(fill=tk.BOTH, expand=1)

        self.user_status_var = tk.StringVar()
        self.user_status_var.set("登陆状态")
        self.login_status_label = tk.Label(master=self.right_frame_list[1], textvariable=self.user_status_var,
                                           font=('微软雅黑', 15), bg="#aeddfb", fg="green")
        self.login_status_label.pack(pady=10)
        self.login_button = tk.Button(master=self.right_frame_list[1], font=('微软雅黑', 15), text="点击登陆", bg="#aeddfb",
                                      relief=tk.GROOVE, command=self.show_login_window)
        self.login_button.pack(pady=10)

        self.login_button = tk.Button(master=self.right_frame_list[1], font=('微软雅黑', 15), text="退出登陆", bg="#aeddfb",
                                      fg="red",
                                      relief=tk.GROOVE, command=self.user_logout)
        self.login_button.pack(pady=10)

    def create_frame2(self):
        yscroll = tk.Scrollbar(self.right_frame_list[2], orient=tk.VERTICAL)
        yscroll.grid(rowspan=3, column=1, sticky=tk.NS)

        self.movie_detail_var = tk.StringVar()
        self.movie_detail_var.set("未查询视频")
        self.movie_detail = tk.Label(master=self.right_frame_list[2], textvariable=self.movie_detail_var, bg="white",
                                     width=80, font=('微软雅黑', 13), fg="#0680d7")
        self.movie_detail.grid(row=0, column=0, sticky=tk.NSEW)
        # show='headings', 可以隐藏第一列,height=30,表示最多显示多少条数据
        self.table_2 = ttk.Treeview(self.right_frame_list[2], show='headings', height=30,
                                    yscrollcommand=yscroll.set)  # 创建表格对象
        self.table_2["columns"] = ("page_num", "page_name", 'cid', 'page_url', 'movie_title')  # 定义列
        self.table_2["displaycolumns"] = ("page_num", "page_name")  # 定义显示的列

        self.table_2.heading("page_num", text="集数")  # 设置显示的表头名
        self.table_2.heading("page_name", text="标题")

        self.table_2.column("page_num", anchor="center")  # 设置列
        self.table_2.column("page_name", anchor="w")
        # 数据的插入在查询完毕再插入
        self.table_2.grid(row=1, column=0, sticky=tk.NSEW)
        self.add_ready_btn = tk.Button(master=self.right_frame_list[2], text="添加到下载队列中", font=("微软雅黑", 16),
                                       bg="#9bb6d2",
                                       relief=tk.FLAT, command=self.event_page_select)
        self.add_ready_btn.grid(row=2, column=0, sticky=tk.EW)

        yscroll.config(command=self.table_2.yview)

    def create_frame3(self):
        yscroll = tk.Scrollbar(self.right_frame_list[3], orient=tk.VERTICAL)
        yscroll.grid(rowspan=3, column=1, sticky=tk.NS)

        self.down_queue_var = tk.StringVar()
        self.down_queue_var.set("下载队列")
        self.down_queue = tk.Label(master=self.right_frame_list[3], textvariable=self.down_queue_var, bg="white",
                                   font=('微软雅黑', 13), fg="#0680d7")
        self.down_queue.grid(row=0, column=0, sticky=tk.NSEW)

        self.table_3 = ttk.Treeview(self.right_frame_list[3], show='headings', height=30,
                                    yscrollcommand=yscroll.set)  # 创建表格对象
        self.table_3["columns"] = ('movie_title', "page_num", "page_name", 'cid', 'status', 'page_url')  # 定义列
        self.table_3["displaycolumns"] = ('movie_title', "page_num", "page_name", 'status')  # 定义显示的列
        self.table_3.heading("page_num", text="集数")  # 设置显示的表头名
        self.table_3.heading("movie_title", text="视频名")
        self.table_3.heading("page_name", text="标题")
        self.table_3.heading("status", text="进度")

        self.table_3.column("page_num", anchor="center")  # #设置列
        self.table_3.column("page_name", anchor="w")
        self.table_3.column("movie_title", anchor="w")
        self.table_3.column("status", anchor="center")
        # 数据的插入在查询完毕再插入
        self.table_3.grid(row=1, column=0, sticky=tk.NSEW)

        self.start_down = tk.Button(master=self.right_frame_list[3], text="开始下载", font=("微软雅黑", 16), bg="#9bb6d2",
                                    relief=tk.FLAT, command=self.event_start_down)
        self.start_down.grid(row=2, column=0, sticky=tk.EW)

        yscroll.config(command=self.table_3.yview)

    def create_frame4(self):
        yscroll = tk.Scrollbar(self.right_frame_list[4], orient=tk.VERTICAL)
        yscroll.grid(rowspan=3, column=1, sticky=tk.NS)

        self.downed_var = tk.StringVar()
        self.downed_var.set("已完成下载")
        self.downed_queue = tk.Label(master=self.right_frame_list[4], textvariable=self.downed_var, bg="white",
                                     font=('微软雅黑', 13), fg="#0680d7")
        self.downed_queue.grid(row=0, column=0, sticky=tk.NSEW)
        self.table_4 = ttk.Treeview(self.right_frame_list[4], show='headings', height=30,
                                    yscrollcommand=yscroll.set)  # 创建表格对象
        self.table_4["columns"] = ("movie_title", "page_num", "page_name", 'cid', 'status')  # 定义列
        self.table_4["displaycolumns"] = ("movie_title", "page_num", "page_name", 'status')  # 定义显示的列
        self.table_4.heading("page_num", text="集数")  # 设置显示的表头名
        self.table_4.heading("movie_title", text="视频名")
        self.table_4.heading("page_name", text="标题")
        self.table_4.heading("status", text="进度")

        self.table_4.column("page_num", anchor="center")  # #设置列
        self.table_4.column("movie_title", anchor="w")
        self.table_4.column("page_name", anchor="w")
        self.table_4.column("status", anchor="center")
        # 数据的插入在查询完毕再插入
        self.table_4.grid(row=1, column=0, sticky=tk.NSEW)

        self.delete_finished_btn = tk.Button(master=self.right_frame_list[4], text="清空完成列表", font=("微软雅黑", 16),
                                             bg="#9bb6d2",
                                             relief=tk.FLAT, command=self.event_delete_finished_data)
        self.delete_finished_btn.grid(row=2, column=0, sticky=tk.EW)

        yscroll.config(command=self.table_4.yview)

    def create_frame5(self):
        self.app_declaration = tk.Label(master=self.right_frame_list[5], text=declaration, bg="white",
                                     font=('微软雅黑', 13), fg="#0680d7")
        self.app_declaration.pack()

class Application(ApplicationUI):
    def __init__(self, configer=None):
        self.configer = configer  # 配置对象
        self.user_file = configer.user_file  # 存放用户信息文件
        self.bg_photo = configer.tk_image  # 背景图片
        self.temp_dirname = configer.config_data['temp_dirname']  # 临时缓存音频文件目录
        self.result_dirname = configer.config_data['result_dirname']  # 合并之后的存放目录
        self.down_threading_num = configer.config_data['down_threading_num']  # 下载线程数
        self.now_show_frame_index = configer.config_data['now_show_frame_index']  # 全局目前显示的frame

        self.movie_url = None  # 当前搜索的视频url
        self.movie_title = None  # 当前搜索的视频title
        self.search_movie_result = []  # 搜索视频的章节列表
        self.ready_down_movie = Queue()  # 准备就绪,需要下载的视频队列
        self.init_finished_movie = Queue()  # 初始化完成的队列,剩下的任务就是下载音频
        # ApplicationUI.__init__(self, configer)#执行父类初始化方法
        super().__init__(configer)
        self.check_internet_and_version()  # 检查网络以及最新版本
        self.load_user_fav()  # 加载用户收藏夹

    def browser_go_b_index(self):
        webbrowser.open_new(url="https://www.bilibili.com/")
        "https://space.bilibili.com/472039858/favlist"

    def browser_go_fav_index(self):
        if self.cookie:
            user_id = self.cookie['DedeUserID']
            webbrowser.open_new(url="https://space.bilibili.com/{}/favlist".format(user_id))
        else:
            tk.messagebox.showinfo(title='账号错误', message='我的天啊!你的账号未登录,我怎么前往远方?')

    def browser_go_down(self):
        webbrowser.open_new(url=self.configer.version_data['new_url'])

    def user_logout(self):
        if messagebox.askokcancel("退出账户", "退出账号,你的用户信息将会清空!\n你确定要退出么?"):
            self.cookie = ""
            self.save_user_info(cookie=self.cookie,info='')
            self.fav_list = dict()
            self.fav_combobox["value"] = list()
            self.user_status_var.set("账号未登录")
            tk.messagebox.showinfo(title='退出登陆', message='账号已成功退出!\n登陆信息已失效!')

    def show_login_window(self):
        new_window = tk.Toplevel(self.master)
        new_window.focus_force()  # focus到当前窗口
        new_window.config(bg='#f2f2f2')
        new_window.geometry(f'{int(self.configer.win_width / 3)}x{int(self.configer.win_height / 2)}+600+180')
        new_window.title('扫码登陆')
        new_window.iconphoto(False, self.configer.window_icon[1])
        new_window.resizable(0, 0)

        login_obj = ScanLogin()
        self.tk_image = login_obj.gen_code()
        qrcode_img = tk.Label(new_window, image=self.tk_image, width=250, height=250)
        qrcode_img.pack(pady=30)
        status_var = tk.StringVar()
        status_var.set("还未扫码,请扫码!")
        scan_status = tk.Label(new_window, textvariable=status_var, bg="white", font=("微软雅黑", 15), fg="#04aeda")
        scan_status.pack()

        def check_scan_result():
            while True:
                try:
                    res = login_obj.get_scan_result()
                except:
                    status_var.set("扫码超时,请重新获取!")
                    break
                scan_res = res.json()
                # 判断扫码成功
                if scan_res['status']:
                    status_var.set("扫码成功!正在登陆,请稍等...")
                    cookies = requests.utils.dict_from_cookiejar(res.cookies)
                    #用户个人信息api
                    api=f"https://api.bilibili.com/x/space/acc/info?mid={cookies['DedeUserID']}&jsonp=jsonp"
                    user_info=requests.get(api,cookies=cookies).json()
                    # 把用户cookie,以及用户信息保存到配置文件中
                    self.save_user_info(cookies,user_info['data'])
                    # 加载登陆用户的收藏夹
                    self.load_user_fav()
                    status_var.set("登陆成功!")
                    time.sleep(1)
                    new_window.destroy()
                    break
                else:
                    if scan_res['data'] == -4:
                        status_var.set("还未扫码,请扫码!")
                    elif scan_res['data'] == -5:
                        status_var.set("已扫描二维码,还没确认!")
                time.sleep(2)

        # 开启线程进行判断扫描结果
        t = threading.Thread(target=check_scan_result)
        t.setDaemon(True)
        t.start()

    def show_new_version_window(self):
        new_window = tk.Toplevel(self.master)
        new_window.focus_force()  # focus到当前窗口
        new_window.config(bg='#f2f2f2')
        new_window.geometry(f'{int(self.configer.win_width / 2)}x{int(self.configer.win_height / 2)}+500+180')
        new_window.title('版本更新提醒')
        new_window.iconphoto(False, self.configer.window_icon[1])
        new_window.resizable(0, 0)
        text = "有新版本更新,当前版本为{},最新版本为{}".format(
            self.configer.version_data['user_version'],
            self.configer.version_data['new_version'])
        tip_label = tk.Label(master=new_window, text=text)
        tip_label.pack()
        tip_label.config(font=('微软雅黑', 15))
        outputbox = HTMLScrolledText(new_window, background="white", html=self.configer.version_data['version_desc'])
        outputbox.pack(fill=tk.BOTH, expand=1)
        outputbox.config(state=tk.DISABLED)  # 不可编辑
        outputbox.fit_height()
        go_down_btn = tk.Button(master=new_window, text="前往下载", command=self.browser_go_down)
        go_down_btn.pack(side=tk.LEFT, padx=50, pady=10)
        cancel_down_btn = tk.Button(master=new_window, text="取消更新", command=new_window.destroy)
        cancel_down_btn.pack(side=tk.RIGHT, padx=50, pady=10)
        go_down_btn.config(bg="#6bd1fe", font=('微软雅黑', 15), relief=tk.FLAT)
        cancel_down_btn.config(bg="#ff5370", font=('微软雅黑', 15), relief=tk.FLAT)

    def check_internet_and_version(self):
        # 判断是否正常请求.如果为True,说明网络正常!
        if self.configer.internet:
            # 判断用户该版本是否可用
            if not self.configer.version_data['user_app_is_valid']:
                tk.messagebox.showwarning(title='版本问题', message='【版本维护】该版本正在维护或版本太老,暂不可用!\n请关注新版本的发布.感谢支持!')
                self.master.destroy()
                return None

            # 已经发布了最新的版本,提醒用户前往下载
            if self.configer.version_data['new_version'] != self.configer.version_data['user_version']:
                self.show_new_version_window()

            # 网络正常,但是背景图片加载失败,可能图片链接有问题
            if not self.bg_photo[0]:
                tk.messagebox.showwarning(title='背景图片加载', message='我的天,什么情况?\n未能成功加载背景图片!\n可能配置文件图片链接失效了....')
        else:
            tk.messagebox.showwarning(title='网络问题', message='【网络异常】,请退出检查你的网络!')
            return None

    def check_user_login(self):
        with open(self.user_file, 'r', encoding='utf8') as fp:
            config_data = json.load(fp)
            self.cookie = config_data.get('cookie',"")
            self.user_info=config_data.get('info',"")
            if self.cookie:
                return True
            else:
                return False

    # 程序初始化任务,加载用户收藏夹
    def load_user_fav(self):
        # 如果有网络,根据用户配置文件 查询收藏夹信息
        if self.configer.internet:
            if self.check_user_login():
                self.user_status_var.set(f"登录账号:{self.user_info['name']}\n"
                                         f"等级:{self.user_info['level']}\n"
                                         f"会员:{'普通会员'if self.user_info['vip']['status'] else '大会员'}")
                self.master.title(f"{self.window_title}------{self.user_info['sign']}({self.user_info['name']})")
                try:
                    self.fav_obj = util.UserCollection(self.user_file)
                    for fav_dir in self.fav_obj.get_user_fav_list()['data']['list']:
                        self.fav_list[fav_dir['title']] = fav_dir['id']
                    self.fav_combobox["value"] = list(self.fav_list.keys())
                except:
                    tk.messagebox.showwarning(title='登陆信息', message='老铁,你的登陆信息有误!\n或许信息登陆信息失效,请重新登陆!')
            else:
                self.user_status_var.set("账号未登录!")
                tk.messagebox.showwarning(title='登陆信息', message='未登陆账号,请先登陆账号使用!')

    # 切换frame
    def change_frame(self, frame_index):
        self.right_frame_list[self.now_show_frame_index].grid_forget()
        self.button_list[self.now_show_frame_index].config(bg="#9bb6d2")
        self.right_frame_list[frame_index].grid(row=0, column=1, padx=self.frame_list_xy[frame_index][0],
                                                pady=self.frame_list_xy[frame_index][1])
        self.button_list[frame_index].config(bg="white")  # active 颜色
        self.right_frame_list[frame_index].grid_propagate(0)
        self.now_show_frame_index = frame_index

    def on_closing(self):
        if messagebox.askokcancel("退出", "执行的任务将会被终止!\n你确定要退出么?"):
            self.master.destroy()

    def on_enter(self, event):
        event.widget.config(bg="white")

    def on_leave(self, event):
        if self.button_list[self.now_show_frame_index] != event.widget:
            event.widget.config(bg="#9bb6d2")

    # 点击按钮触发切换显示对应的frame
    def show_frame(self, event):
        button_index = self.button_value.index(event.widget.config('text')[-1])
        self.change_frame(button_index)

    # 清空表格
    @staticmethod
    def del_table(table):
        items = table.get_children()
        for item in items:
            table.delete(item)

    # 当点击具体收藏夹触发
    def even_selected_dir(self, event):
        self.select_fav_movie.set("选择收藏夹视频")
        self.fav_movie_list.clear()
        dir_id = self.fav_list.get(self.select_fav.get())
        movie_list = self.fav_obj.get_user_fav_movie_list(dir_id=dir_id)['data']['medias']
        for i in movie_list:
            self.fav_movie_list[i['title']] = r"https://www.bilibili.com/video/" + i['bvid']
        self.fav_movie_combobox["value"] = list(self.fav_movie_list.keys())

    # 当点击收藏夹具体视频触发
    def even_selected_movie(self, event):
        url = self.fav_movie_list.get(self.select_fav_movie.get())
        self.event_search_movie(url=url)

    # 当点击添加下载队列触发
    def event_page_select(self):
        select_count = 0
        for i, item in enumerate(self.table_2.selection()):
            select_count += 1
            item_text = self.table_2.item(item, "values")
            ready_item = self.table_3.insert("", i, text=f"line{i}",
                                             values=(item_text[4], item_text[0], item_text[1], item_text[2], '准备就绪',
                                                     item_text[3]))
            self.ready_down_movie.put(ready_item)
            self.table_2.delete(item)
        tk.messagebox.showinfo(title='添加成功', message=f'已成功添加到下载队列!\n本次共添加下载任务:{select_count} 个')

    # 当点击清空完成任务列表触发
    def event_delete_finished_data(self):
        self.del_table(self.table_4)

    # 当点击开始下载队列任务触发
    def event_start_down(self):
        def init_worker():
            while not self.ready_down_movie.empty():
                item_obj = self.ready_down_movie.get()
                item = self.table_3.item(item_obj, "values")
                self.table_3.item(item_obj, values=(item[0], item[1], item[2], item[3], '正在初始化', item[5]))
                # 创建初始化下载对象
                try:
                    down_obj = util.DownMovie(cid=item[3], movie_title=item[0], page_name=item[2], page_url=item[5],
                                              cookie=self.cookie, result_dirname=self.result_dirname,
                                              temp_dirname=self.temp_dirname)
                except:
                    # 下载失败
                    self.table_3.item(item_obj, values=(item[0], item[1], item[2], item[3], '初始化失败', item[5]))
                    continue

                self.ready_down_movie.task_done()  # 该任务完成
                # 将初始化完成的对象放在队列里
                self.init_finished_movie.put((down_obj, item_obj))
                self.table_3.item(item_obj, values=(item[0], item[1], item[2], item[3], '已初始化', item[5]))

        def down_av_work():
            while True:
                try:
                    queue_get = self.init_finished_movie.get(block=True, timeout=30)
                except Empty as e:
                    break
                init_obj = queue_get[0]
                row_obj = queue_get[1]
                item = self.table_3.item(row_obj, "values")
                self.table_3.item(row_obj, values=(item[0], item[1], item[2], item[3], '下载就绪', item[5]))
                t_video = threading.Thread(target=init_obj.down_video, args=(self.table_3, row_obj))
                t_audio = threading.Thread(target=init_obj.down_audio)
                t_video.start()
                t_audio.start()
                t_video.join()
                t_audio.join()
                self.init_finished_movie.task_done()
                self.table_3.item(row_obj, values=(item[0], item[1], item[2], item[3], '音频合并', item[5]))
                result = init_obj.compose()  # 进行音频合并
                if not result:
                    self.table_3.item(row_obj, values=(item[0], item[1], item[2], item[3], '音频合并失败', item[5]))
                else:
                    self.table_3.delete(row_obj)
                    self.table_4.insert('', 0, values=(item[0], item[1], item[2], item[3], '已完成', item[5]))

        for i in range(self.down_threading_num):
            if i <= 2:
                t = threading.Thread(target=init_worker)
                t.start()
            else:
                t2 = threading.Thread(target=down_av_work)
                t2.daemon = True  # 设置为守护线程,程序本身是主线程,当退出程序,守护线程就会消亡
                t2.start()

    # 当根据链接点击搜索视频触发
    def event_search_movie(self, url=None):
        if self.cookie:

            new_url = url if url else self.search_input.get()
            if new_url == '':
                tk.messagebox.showerror(title='出现错误', message='抱歉,你输入的url为空')
            else:
                self.movie_url = new_url.split('?')[0]
                bili_obj = util.Bilibili(movie_url=new_url, user_file=self.user_file)
                self.movie_url = new_url.split('?')[0]
                self.movie_title = bili_obj.get_movie_base_info()['title']
                self.movie_detail_var.set(self.movie_title)
                self.search_movie_result = bili_obj.get_movie_pages_info()['data']
                # 先清空表格
                self.del_table(self.table_2)
                for i, item in enumerate(self.search_movie_result):
                    self.table_2.insert("", i, text=f"{item['cid']}", values=(
                        str(item['page']), f"P{item['page']}_" + item['part'], item['cid'],
                        self.movie_url + "?p=" + str(item['page']),
                        self.movie_title))
                # 转页面到下载详情
                self.change_frame(2)
        else:
            tk.messagebox.showinfo(title='账号错误', message='未登陆账号,没有通行证,不可以通过!')

    # 保存登陆用户信息
    def save_user_info(self, cookie,info):
        with open(self.user_file, 'r+', encoding='utf8') as fp:
            user_info = json.load(fp)
            user_info['cookie'] = cookie
            user_info['info'] = info
            fp.seek(0)
            json.dump(user_info, fp)
            fp.truncate()


class ScanLogin:
    def __init__(self):
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.49"
        }
        self.res = self.ask_qrcode_url()
        self.code_url = self.res['data']['url']
        self.oauthKey = self.res['data']['oauthKey']

    def ask_qrcode_url(self):
        api = "http://passport.bilibili.com/qrcode/getLoginUrl"
        response = requests.get(url=api, headers=self.headers).json()
        return response

    def gen_code(self):
        img = qrcode.make(self.code_url)
        pil_image = img.resize((300, 300), Image.ANTIALIAS)  # 更改大小
        tk_image = ImageTk.PhotoImage(pil_image)
        return tk_image

    def get_scan_result(self):
        api = "http://passport.bilibili.com/qrcode/getLoginInfo"
        res = requests.post(url=api, data={"oauthKey": self.oauthKey}, headers=self.headers)
        return res


if __name__ == '__main__':
    configer = Config()
    app = Application(configer=configer)
    configer.window.protocol('WM_DELETE_WINDOW', app.on_closing)  # 全局触发关闭事件
    configer.window.mainloop()
